<?php
/**
 * basic reference
 *
 * @version:	0.1
 * @package:	global
 * @author:	alex_ez
 * @created:	12.02.2010 05:21
 *
 * @copyright:	(c) 2010 alex <qfox@ya.ru> yaroshevich aka alex_ez. All rights reserved.
 */


abstract class basic_reference_admin_controller extends admin_controller
{
	protected $model = null;
	protected $_title = '';
	protected $_titles = '';
	
	protected $form = null;
	protected $filter = null;
	
	protected $empty = array( 'id' => 'new', 'tag' => '', 'value' => '' );
	protected $order = 'id+';
	protected $lists = array( );
	
	protected $that = null;
	protected $roles = null;
	protected $haveroles = null;
	
	public function on_start( )
	{
		parent::on_start( );
		$this ->form = new form( $this );
		$this ->form ->set_option( 'action', $this ->get_inner_url( 1 ) );
		$this ->form ->set_lists( $this ->lists );
		
		$this ->filter = new filter( $this, null, array( 'action' => './', 'mode' => 'limited' ) );
		$this ->filter ->set_lists( $this ->lists );
		
		if( !$this ->_title ) $this ->_title = 'record in '.get_class( $this ->model );
		if( !$this ->_titles ) $this ->_titles = get_class( $this ->model );
		$this ->_titles = mb_convert_case($this ->_titles,MB_CASE_TITLE);
	}
	
	public function page_index( $p, $o )
	{
		$this ->check_roles( 'index' );
		
		$r = array( );
		
		$o = mb_strtolower( (string)( _::pick( Request::instance( ) ->g_order, $this ->order ) ) );
		$d = substr( $o, -1, 1 ) == '-' ? '-' : '+';
		$o = trim($o,'+-');
		
		// filter
		$r['filter'] = $this ->filter ->get_form_data( );
		$w = $this ->filter ->get_where_data( );

		// limit with paging
		$quantity = $this ->filter ->get_limit_value( );
		$page = min( max( _::pick( (int)(request::instance( ) ->g_page), 1 ), 1 ), 500 );
		$limit = array( ($page-1)*$quantity, $quantity );

		// limit with no paging
		//$limit = array( 0, $this ->filter ->getLimitValue( ) );
		
		// store for remove and put to orders
		$this ->visitor ->storedquery = $this ->filter ->get_query( array( 'order' => $o.$d, 'page' => $page ) );
		
		// cols
		$__q = $this ->filter ->get_query( ); $__q .= !empty($__q)?'&':'';
		$cols = array_keys( $this ->empty );
		$r['cols'] = '';
		foreach( $cols as $k )
		$r['cols'] .= mb_convert_case($k,MB_CASE_TITLE)
			.($o==$k?' '.($d=='+'?'↓':'↑'):'').'::href=?'.$__q.'order='.$k.($o==$k&&$d=='+'?'-':'').($o==$k?':class=common':'').'|';
		$r['cols'] = rtrim( $r['cols'], '|' );
		
		// items
		$r['items'] = $this ->get_items( $w, $o.$d, $limit );
		$found_rows = $this ->get_found_rows( );
		
		/** pager */
		$r['count'] = $found_rows;
		$r['pager'] = array( 'current' => $page, 'total' => intval( ($found_rows-1) / $quantity ) + 1, 'parallax' => 10 );
		$r['pager']['url_template'] = './?'.$this ->filter ->get_query( array( 'order' => $o.$d, 'page' => '@p' ) );
		/** /pager */

		// +buttons
		$buttonsCount = 0;
		foreach( array_keys( $r['items'] ) as $k )
		{
			$r['items'][$k] = $this ->handle_row( 'index', $r['items'][$k], $k );
			$r['items'][$k]['buttons'] = $this ->render_row_controls( $r['items'][$k], $k );
			$buttonsCount = max( $buttonsCount, substr_count( $r['items'][$k]['buttons'], '"ibutton' ) );
		}
		if( $buttonsCount > 0 )
		$r['cols'] .= '| :'.intval($buttonsCount*20+5).'px';
		
		$r['count'] = $this ->model ->get_found_rows( );
		$r['title'] = 'Reference «'.texo::translate($this->_titles).'»';
		$r['template'] = 'admin/__list.tpl';
		
		return $r;
	}
	
	protected function get_items( $w = '', $o = null, $limit = null )
	{
		return $this ->model ->by( $w, $o, $limit, -1 );
	}
	
	protected function get_found_rows( )
	{
		return $this ->model ->get_found_rows( );
	}
	
	protected function render_row_controls( $v, $k = null, $mode = null )
	{
		$r = '';
		
		if( is_null( $mode ) )
		{
			$mode = '';
			if( !$this ->is_removable( $v, $k ) ) $mode .= 'noremove';
			if( !$this ->is_editable( $v, $k ) ) $mode .= 'noedit';
		}
		
		if( is_null( $mode ) || stripos( $mode, 'noedit' ) === false )
		$r .= sprintf( '<a class="ibutton edit" href="./edit/?id='.$v['id'].'" title="'._('Edit').'"><!-- --></a>' );
		if( is_null( $mode ) || stripos( $mode, 'noremove' ) === false )
		$r .= sprintf( '<a class="ibutton delete confirm" href="./remove/?id='.$v['id'].'" title="'._('Remove').'"><!-- --></a>' );
		
		return $r;
	}
	
	protected function handle_row( $page, $v, $k = null )
	{
		return $v;
	}
	
	protected function is_removable( $v, $k = null )
	{
		return true;
	}
	
	protected function is_editable( $v, $k = null )
	{
		return true;
	}
	
	public function page_edit( $p, $o )
	{
		$id = Request::instance( ) ->g_id;
		$id = ( $id == 'new' || $id == -1 ) ? 'new' : (int)($id);
		$new = ( $id === 'new' );
		
		$this ->check_roles( $new ? 'add' : 'edit' );
		
		$d = $new
			? $this ->empty
			: $this ->model ->get( $id );
		$d = $this ->handle_row( $new ? 'add' : 'edit', $d, $id );
		
		if( !$d ) response::instance( ) ->notfound( );
		if( !$this ->is_editable( $d, $id ) ) return response::instance( ) ->forbidden( );
		
		//unplain text and desc fields
		foreach( array( 'text', 'desc' ) as $kavo ) if( isset( $this ->empty[ $kavo ] ) ) $d[ $kavo ] = texo::unplain( @$d[ $kavo ] );
		
		$this ->form ->set_data( $d );
		
		$r = array( );
		$r['title'] = $new
			? sprintf(__('New %s'),$this ->_title)
			: sprintf(__('Edit %s'),$this ->_title);
		
		$r['fields'] = $this ->form ->get_field_set( );
		$r['options'] = $this ->form ->get_options( );
		$r['template'] = 'admin/__form.tpl';
		
		return $r;
	}

	
	public function ajax_edit( $z )
	{
		$this ->check_roles( 'edit' );
		
		$id = Request::instance( ) ->g_id;
		$id = ( $id == 'new' || $id == -1 ) ? 'new' : (int)($id);
		$new = ( $id === 'new' );
		
		// fetch post data if data is bogus return error
		try { $p = $this ->form ->get_post_data( ); } catch( form_exception $e ) { return array( 'error' => $e ->getMessage() ); }
		
		if( isset( $this ->empty['tag'] ) && empty( $p['tag'] ) )
			$p['tag'] = strtolower( texo::latinate( _::pick( @$p['name'], @$p['title'], @$p['value'], rand(10000,99999) ) ) );
		
		// plain text and desc fields
		//foreach( array( 'text', 'desc' ) as $kavo ) if( isset( $this ->empty[ $kavo ] ) ) $p[ $kavo ] = texo::plain( @$p[ $kavo ] );
		
		$errors = array( );
		$p = $this ->handle_row( 'beforeajax'.($new ? 'add' : 'edit'), $p, $id );
		if( !$this ->is_editable( $p, $id ) ) return array( 'error' => texo::translate('Cant store') );
		if( $new ) {
			$id = $this ->model ->add( $p );
			if( !$id ) $errors[] = texo::translate('Not stored.');
		} else {
			$eo = $this ->model ->edit( $id, $p );
			if( $eo!=1 ) $errors[] = texo::translate('Not stored.');
		}
		
		if( $id > 0 )
		{
			$error = $this ->handle_row( 'ajax'.($new ? 'add' : 'edit'), $p, $id );
			if( is_subclass_of( $this ->that, 'controller' ) ) // linked
				$errors[] = is_null( $error ) ? texo::translate( 'Data linked' ) : $error;
		}
		
		if( empty($errors) ) $errors[] = texo::translate('Stored!');
		
		return array( 'message' => join( ', ', $errors ), 'location' => '../', 'confirm' => true );
	}
	
	public function page_remove( $p, $o )
	{
		$this ->check_roles( 'remove' );
		
		$id = (int)Request::instance( ) ->g_id;
		$item = $this ->model ->get( $id );
		
		if( !$item ) {
			$r['out'] = _('Item not found');
		} elseif( $this ->is_removable( $item, $id ) ) {
			$removed = $this ->model ->remove( $id );
			$r['out'] = texo::translate('Item removed', '%s items removed', $removed);
		} else {
			$r['out'] = texo::translate('Non-removable item');
		}
		
		$r['title'] = _('Remove '.$this ->_title);
		$r['template'] = 'admin/__out.tpl';
		$r['links'] = array(
			array( 'href' => '../?'.$this ->visitor ->storedquery, 'title' => 'К выборке' ),
			array( 'href' => '../', 'title' => 'К полному списку' ),
			);
		
		return $r;
	}
	
	protected function check_roles( $tag = null, $return = false )
	{
		if( is_null( $this ->haveroles ) && is_null( $this ->roles ) )
			return true;
		
		if( is_null( $this ->haveroles ) && !is_null( $this ->roles ) )
			$this ->haveroles = $this ->visitor ->roles ->any( $this ->roles );
		
		if( !is_null( $this ->haveroles ) && $this ->haveroles === true ) return true;
		
		if( $return === true ) return false;
		response::instance( ) ->forbidden( );
		
	}
	
	protected $field_sets;
	protected $field_sets_default =
"{
'id':	{type:static,label:'id',value:''},
'tag':	{type:static,label:'Tag',value:''},
'value':{type:string,label:'Value',required:true},
}";

	
	public function get_field_set( $url = null, $decode = false )
	{
		$iurl = !is_null( $url ) ? $url : $this ->get_inner_url( );
		
		$r = isset( $this ->field_sets[ $iurl ] )
			? ( $url == '_default_' ? $this ->field_sets_default : $this ->field_sets[ $iurl ])
			: null; //json::decode( $fields );
		
		return $decode ? json::decode( $r ) : $r;
	}
	
	public function get_inner_url( $ajax = false )
	{
		$url = str_replace( 'ajax/', '', Request::instance( ) ->get_url( ) );
		$url = parse_url( $url );
		$r = trim( $url['path'], '/' );
		
		if( $ajax )
			$r = '/ajax/'.$r.'/'.(@$url['query']?('?'.$url['query']):'');
		
		return $r;
	}
	
}


?>